---@class Battle.BufferMgr
local BufferMgr = Battle.CreateClass("BufferMgr")
Battle.BufferMgr = BufferMgr
local this = BufferMgr

function BufferMgr.OnCreate()
    ---@type table<number,Battle.Buffer[]>
    this.bufferList = {}
    ---@type Battle.Buffer[]
    this.removedList = {}
    this.buffEffects = {}
    ---@type Battle.Buffer[][][]
    --this.signGroupBuff ={{},{}}--分队储存指定群体组buff
    Battle.ClientBattle:RegisterUpdateCallback(this.Update)
end
function BufferMgr.OnDestroy()
    if this.bufferList then
        for k, v in pairs(this.bufferList) do
            for id, buff in pairs(v) do
                buff:OnDestroy()
            end
        end
    end
    this.bufferList = nil
end
function BufferMgr.GetBuffList(targetId)
    return this.bufferList[targetId]
end
---@return Battle.Buffer
function BufferMgr.GetBuff(targetId, buffId)
    local _list = this.bufferList[targetId]
    if not _list then
        return nil
    end
    return _list[buffId]
end
function BufferMgr.CreateBuff(buffId, overlay, targetId, during, sourceSender,sourceSkillId,sourceBuffId)
    if not this.AddBuffBefore(buffId,targetId) then
        return
    end
    local b = Battle.PoolMgr.GetBufferFromPool()--Battle.Buffer.New()
    b:OnCreate()
    b:Set(buffId, overlay, targetId, during, sourceSender,sourceSkillId,sourceBuffId)
    b.buffScript = this.LoadBuffEffect(b);
    this.AddBuff(b)
end
function BufferMgr.AddBuffBefore(buffId,targetId)
    local list = this.GetBuffList(targetId)
    if not list then return true end

    local actor = Battle.ActorManager.GetActor(targetId)
    local param = decodeJsonStrToTable(DataTable.GetById("t_buff",buffId,"f_Sign"))
    if param then
        for k,v in pairs(param) do
            if actor.signSystem:HasSign(v) then
                --互斥不添加buff
                return false
            end
        end
    end
    return true
end
---@param buff Battle.Buffer
function BufferMgr.ToPool(buff)
    if buff == nil then
        return
    end
    buff:OnDestroy()
    local _list = this.bufferList[buff.targetId]
    if _list then
        _list[buff.buffId] = nil
    end
    Battle.PoolMgr.ReturnBufferToPool(buff)
end
---@param buff Battle.Buffer
function BufferMgr.AddBuff(buff)
    local list = this.GetBuffList(buff.targetId)
    if not list then
        list = {}
        this.bufferList[buff.targetId] = list
    end
    if list[buff.buffId] ~= nil then
        return
    end
    if buff.cfg.f_TriggerOpportunity > 0 then
        local listener = this._innerActionListener.New(buff.targetId, buff,buff.cfg.f_TriggerOpportunity)
        Battle.EventManager.addEventListener(buff.cfg.f_TriggerOpportunity, buff.targetId, listener)
    end
    if buff.cfg.f_RemoveOpportunity > 0 then
        local listener = this._innerRemoveListener.New(buff.targetId, buff)
        EventManager.addEventListener(buff.cfg.f_RemoveOpportunity, buff.targetId, listener)
    end
    list[buff.buffId] = buff
    Battle.EventManager.notifyEventListener(Battle.BuffTriggerType.ADD, buff.targetId)

end
---buffId 为 nil 删除所有的buff
function BufferMgr.RemoveBuff(targetId, buffId)
    local buffList = this.bufferList[targetId]
    if not buffList then return  end
    local buff = buffList[buffId]
    if not buff then return end

    buff:OnBuffRemove()
    Battle.EventManager.removeEventListener(buff.cfg.f_TriggerOpportunity, targetId, buff.buffId .. "_ACTION")
    Battle.EventManager.removeEventListener(buff.cfg.f_RemoveOpportunity, targetId, buff.buffId .. "_REMOVE")
    local target = Battle.ActorManager.GetActor(targetId)

    --移除后添加buff
    if buff.cfg.f_RemoveBuffAdd and buff.cfg.f_RemoveBuffAdd ~= "" then
        for i, v in pairs(decodeJsonStrToTable(buff.cfg.f_RemoveBuffAdd)) do
            target:AddBuff(v[1], v[2], nil, target,nil,buffId)
        end
    end
    this.ToPool(buff)
end
function BufferMgr.RemoveBuffList(targetId)
    table.clear(this.removedList)
    local list = this.GetBuffList(targetId)
    if not list then return end
    for k, v in pairs(list) do
        table.insert(this.removedList, v)
    end
    for k, v in pairs(this.removedList) do
        this.RemoveBuff(targetId,v.buffId)
    end
end
function BufferMgr.Update(dt)
    table.clear(this.removedList)
    local temp = TablePool.Get()
    for k, v in pairs(this.bufferList) do
        temp[k] = v
    end
    for k, v in pairs(temp) do
        for id, buff in pairs(v) do
            buff:Update(dt)
            if buff:IsDie() then
                table.insert(this.removedList, buff)
            end
        end
    end
    TablePool.Release(temp)
    --
    for k, v in pairs(this.removedList) do
        this.RemoveBuff(v.targetId,v.buffId)
    end
    table.clear(this.removedList)
end
--获取buff加成的属性
function BufferMgr.countFighterAttribute(actorId)
    local buffList = this.GetBuffList(actorId);
    local buffAttr = {}
    if buffList ~= nil then
        for i, buff in pairs(buffList) do
            if buff.isInDuring then
                if buff.cfg.f_Effect == Battle.BuffEffect.Attribute then
                    for k, v in pairs(decodeJsonStrToTable(buff.cfg.f_EffectParameter)) do
                        if buffAttr[v[1]] == nil then
                            buffAttr[v[1]] = 0;
                        end
                        buffAttr[v[1]] = buffAttr[v[1]] + v[2] * buff.overlay;
                    end
                    --属性添加变化
                end
            end
        end
    end
    return buffAttr;
end
--[[---@param actor Battle.Entity
function BufferMgr.GetBuffTotalState(actor)
    local buffList = this.GetBuffList(actor.id);
    for k, buff in pairs(buffList) do
        if buff.isInDuring then
            if buff.cfg.f_SpecialBuff ~= "" and buff.cfg.f_SpecialBuff ~= nil then
                local special = decodeJsonStrToTable(buff.cfg.f_SpecialBuff);
                for i = 1, #special do
                    actor.effectStateSystem:AddState(special[i])
                end
            end
        end
    end
end]]
--检查buff是否互斥
---@param mainBuff Battle.Buffer
---@param checkBuff Battle.Buffer
function BufferMgr.CheckMutex(mainBuff, checkBuff)
    local mutex = mainBuff.mutexList
    --满足互斥条件
    for k,v in pairs(mutex) do
        if checkBuff:HasSign(k) then
            return true
        end
    end
    return false
end
function BufferMgr.LoadBuffEffect(buff)
    local buffScriptId = buff.cfg.f_Effect;
    if buffScriptId ~= 0 then
        local script = clone(require("Battle/Buffer/BuffEffect/BuffEffect" .. buffScriptId))
        this.buffEffects[buffScriptId] = script.New();
        script:OnCreate(buff)
        return script;
    end
    return nil;
end
--获取buff脚本
function BufferMgr.GetBuffEffect(id)
    local buffEffect = this.buffEffects[id]
    if buffEffect ~= nil then
        return buffEffect
    end
    return nil;
end
--内部类
this._innerActionListener = Battle.CreateClass("_innerActionListener")
---@class BufferMgr._innerActionListener:IFightEventListener
local _innerLis = this._innerActionListener
function _innerLis:ctor(fighterId, buff,triggerType)
    self.fighterId = fighterId
    self.fighter = Battle.ActorManager.GetActor(fighterId)
    ---@type Battle.Buffer
    self.buff = buff
    self.triggerType = triggerType
end
function _innerLis:notify(eventId, ...)
    if self:checkTriggerCondition(...) then
        self.buff:OnBuffStart(...)
        --特殊效果
        Battle.EventManager.notifyEventListener(Battle.BuffTriggerType.ACTIVE, self.buff.targetId)
        --BufferMgr.GetBuffTotalState(self.fighter)
        if self.buff.cfg.f_AddBuff ~= "" then
            for i, v in pairs(decodeJsonStrToTable(self.buff.cfg.f_AddBuff)) do
                self.fighter:AddBuff(v[1], v[2], nil, self.fighter,nil,self.buff.buffId)
            end
        end
    end
    if self.triggerType == Battle.BuffTriggerType.ADD then
        Battle.EventManager.removeEventListener(self.triggerType, self.buff.targetId, self:getId())
    end
end
function _innerLis:getId()
    return self.buff.buffId .. "_ACTION";
end
function _innerLis:priority()
    return self.buff.cfg.f_Priority * 100000 + self.buff.buffId * 10 + 1
end
--触发条件
function _innerLis:checkTriggerCondition(...)
    local param = { ... };
    local flag =  self.buff:CheckSecondCondition(param)
    if flag then
        self.buff:SecondConditionExecute()
    end
    return flag;
end
---内部类
this._innerRemoveListener = Battle.CreateClass("_innerRemoveListener")
---@class BufferMgr._innerRemoveListener:IFightEventListener
local _innerLis1 = this._innerRemoveListener
function _innerLis1:ctor(fighterId, buff)
    self.fighterId = fighterId
    self.fighter = Battle.ActorManager.GetActor(fighterId)
    ---@type Battle.Buffer
    self.buff = buff
end
function _innerLis1:notify(eventId)
    --未到移除时间
    --if self.buff.continuedTime > 0 then
    --    local frame = self.buff.continuedTime / Global.FIGHT_FRAME
    --    if frame > 0 and self.fight.frame < self.buff.startFrame + frame then
    --        return ;
    --    end
    --end
    if eventId == Battle.BuffTriggerType.FRAME then
        return
    end
    -- 移除原有buff
    Battle.BufferMgr.RemoveBuff(self.buff.targetId,self.buff.buffId)
end
function _innerLis1:getId()
    return self.buff.buffId .. "_REMOVE";
end
function _innerLis1:priority()
    return self.buff.cfg.f_Priority * 100000 + self.buff.buffId * 10
end
